#ifndef __zlogger_h__
#define __zlogger_h__
#include "zutilinc.h"
#ifdef __cplusplus
extern "C" {
#endif
enum EZLOGGERPRI
{
	ZLOGGER_LVL_FATAL,
	ZLOGGER_LVL_ALERT,
	ZLOGGER_LVL_CRITICAL,
	ZLOGGER_LVL_ERROR,
	ZLOGGER_LVL_WARNING,
	ZLOGGER_LVL_NOTICE,
	ZLOGGER_LVL_INFO,
	ZLOGGER_LVL_DEBUG,
	ZLOGGER_LVL_TOP,
};

#define ZLOGGERPIDLEN 32

typedef enum
{
	ZLOGGER_DEST_SYSLOG,
	ZLOGGER_DEST_STDOUT,
	ZLOGGER_DEST_MONITOR,
	ZLOGGER_DEST_FILE,
	ZLOGGER_DEST_APP,
	ZLOGGER_DEST_TOP,
} EZLOGGERDEST;

typedef int (*ZLOGGER_APP_FN)(void* p1,void* p2,struct zLoggerPID* pid, int lvl,const char* title,const char* fmt, va_list l);

typedef struct zLoggerPID
{
	void* magic; // auto check const char* or zloggerpid
	char* name;
	int maxlvl[ZLOGGER_DEST_TOP];
	int default_lvl;
	int record_priority;
	char* filename;
	FILE* fp;
	int facility;
	ZLOGGER_APP_FN app_fn;
	void* app_arg1;
	void* app_arg2;
}zLoggerPID;


ZUTIL_API zLoggerPID* zlogger_default();
ZUTIL_API zLoggerPID* zlogger_findpid(const char* name);
ZUTIL_API zLoggerPID* zlogger_getpid(int idx);
ZUTIL_API zLoggerPID* zlogger_new_zLoggerPID(const char* name);
ZUTIL_API void zlogger_free_zLoggerPID(zLoggerPID* p);
ZUTIL_API void zlogger_set_app(zLoggerPID* pid, ZLOGGER_APP_FN pfn, void* p1,void* p2);
ZUTIL_API void zlogger_set_level(zLoggerPID *pid, EZLOGGERDEST, int log_level);
ZUTIL_API int zlogger_set_file(zLoggerPID *pid, const char *filename, int log_level);
ZUTIL_API int zlogger_reset_file(zLoggerPID *pid);
ZUTIL_API int zlogger_lvl_bool(zLoggerPID *pid,int log_level);

// custom hook must call before zlogger_init
ZUTIL_API void zlogger_init(const char* program, const char* cfg);
ZUTIL_API void zlogger_finish();

#ifdef __cplusplus
ZUTIL_API zLoggerPID* ZLOGGER_PID(const char* name,const char* cfg=NULL);
#else
ZUTIL_API zLoggerPID* ZLOGGER_PID(const char* name,const char* cfg);
#endif	

ZUTIL_API const char* zloggerdst2name(int dst);
ZUTIL_API const char* zloggerpri2name(int pri);

ZUTIL_API void zLoggerOut(const char* pfmt, ...);

typedef void* ZLOGGERPID;
typedef zLoggerPID* (*ZLOGGER_PID_FN)(const char* name,const char* cfg);
typedef void (*Z_LOGGEROUT_FN)(const ZLOGGERPID pid, int lvl,const char* fmt, va_list l);
typedef void (*Z_LOGGEROUTKV_FN)(const ZLOGGERPID pid, int lvl,const char* title,const char* fmt, va_list l);

ZUTIL_API ZLOGGER_PID_FN zLoggerSetOutPID(ZLOGGER_PID_FN pfn);
ZUTIL_API Z_LOGGEROUT_FN zLoggerSetOutFn(Z_LOGGEROUT_FN pfn);
ZUTIL_API Z_LOGGEROUTKV_FN zLoggerSetOutKVFn(Z_LOGGEROUTKV_FN pfn);
ZUTIL_API void zLoggerSetOutStub(ZLOGGER_PID_FN ppid,Z_LOGGEROUT_FN pfn,Z_LOGGEROUTKV_FN pkvfn);

#define _FakeDBGPRINT 

#ifndef ZUTIL_DEBUG
	#ifdef Z_DEBUG
		#define ZUTIL_DEBUG
	#endif
#endif

#ifndef ZUTIL_DEBUG
  #define zDbgOut _FakeDBGPRINT
#else
  #define zDbgOut zLoggerOut
#endif

ZUTIL_API void zlogger(const ZLOGGERPID pid, int lvl,const char* fmt,...);
ZUTIL_API void zlogger_va(const ZLOGGERPID pid, int lvl,const char* fmt,va_list l);
ZUTIL_API void zlogger_str(const ZLOGGERPID pid, int lvl,const char*);

/*
title: such as "id,timestamp,data"
fmt: such as "%s,%d,%s"
*/
ZUTIL_API void zloggerkv(const ZLOGGERPID pid, int lvl,const char* title,const char* fmt,...);

ZUTIL_API void zlogger_debug(const ZLOGGERPID pid, const char* fmt,...);
ZUTIL_API void zlogger_info(const ZLOGGERPID pid, const char* fmt,...);
ZUTIL_API void zlogger_notice(const ZLOGGERPID pid, const char* fmt,...);
ZUTIL_API void zlogger_warning(const ZLOGGERPID pid, const char* fmt,...);
ZUTIL_API void zlogger_error(const ZLOGGERPID pid, const char* fmt,...);

#if defined(_MSC_VER) && _MSC_VER < 1300
#define ZCHKLOG 
#define ZCHKDBG 
#define ZCHKINFO 
#define ZCHKNOTICE 
#define ZCHKWARNING 
#else
#define ZCHKLOG(pid,lvl,...) if(zlogger_lvl_bool((pid),lvl)){zlogger(pid,lvl,__VA_ARGS__);}
#define ZCHKDBG(pid,...) if(zlogger_lvl_bool((pid),ZLOGGER_LVL_DEBUG)){zlogger_debug(pid,__VA_ARGS__);}
#define ZCHKINFO(pid,...) if(zlogger_lvl_bool((pid),ZLOGGER_LVL_INFO)){zlogger_info(pid,__VA_ARGS__);}
#define ZCHKNOTICE(pid,...) if(zlogger_lvl_bool((pid),ZLOGGER_LVL_NOTICE)){zlogger_notice(pid,__VA_ARGS__);}
#define ZCHKWARNING(pid,...) if(zlogger_lvl_bool((pid),ZLOGGER_LVL_WARNING)){zlogger_warning(pid,__VA_ARGS__);}
#endif // MSC_VER

#define ZSAFE(a) ((a)?(a):"")
#ifdef __cplusplus
}
#endif
#endif

